package com.xjj.sso.server.filter.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.xjj.framework.XJJConstants;
import com.xjj.framework.spring.SpringBeanLoader;
import com.xjj.sso.project.cache.ProjectCache;
import com.xjj.sso.project.entity.ProjectEntity;
import com.xjj.sso.server.cache.TicketCache;
import com.xjj.sso.server.filter.SSOHandler;
import com.xjj.sso.server.filter.SSOHandlerSupport;
import com.xjj.sso.server.pojo.SSOIdentity;
import com.xjj.sso.server.pojo.User;
import com.xjj.sso.server.ticket.GrantingTicket;
import com.xjj.sso.server.ticket.ServiceTicket;
import com.xjj.sso.server.util.JsonUtil;
import com.xjj.sso.server.util.SSOUtils;
import com.xjj.sso.server.util.URLUtils;
import com.xjj.sso.server.validation.UserAuthService;


public class SSOWebHandler extends SSOHandlerSupport implements SSOHandler{
	
	private static SSOWebHandler ssoHandler = new SSOWebHandler();
	public static SSOHandler getSSOHandler() {
		return ssoHandler;
	}
	
	/**
	 * 验证是否已经单点登录
	 * @param request
	 * @param response
	 * @param chain
	 * @throws IOException
	 * @throws ServletException
	 */
	public void authentication(HttpServletRequest request, HttpServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		String service = request.getParameter("service");
		String projectCode = request.getParameter("projectCode");
		String gtCookie = this.getSSOCookie(request, response);
		GrantingTicket gt = TicketCache.getGrantingTicket(gtCookie);
		
		System.out.println("===================sso authentication begin========================");
		System.out.println("service="+service);
		System.out.println("projectCode="+projectCode);
		System.out.println("gtCookie="+gtCookie);
		System.out.println("===================sso authentication end========================");
		
		if(SSOUtils.isBlank(service) || null == gtCookie || null == gt)
		{
			//如果登录方式是项目登录方式
			if("project".equals(SSO_LOGIN_TYPE))
			{
				//ProjectService projectService = (ProjectService)SpringBeanLoader.getBean("projectServiceImpl");
				ProjectEntity p = ProjectCache.getByCode(projectCode);
				if(null != p)
				{
					Map<String, String[]> requestPram = new HashMap<String, String[]>();
					if(SSOUtils.isNotBlank(service))
					{
						requestPram.put("backURL", new String[]{service});
					}
					
					sendRedirect(request, response, p.getLoginUrl(),requestPram);
					return;
				}
			}
			
			//在sso统一登录
			if("sso".equals(SSO_LOGIN_TYPE))
			{
				sendRedirect(request, response, SSO_URL_LOGIN,null);
				return;
			}
			
			//跳转到sso默认的登录
			sendRedirect(request, response, SSO_URL_LOGIN,null);
			return;
		}
		
		//生成ticket
		ServiceTicket st = GrantingTicket.generateServiceTicket(service);
		st.setProjectCode(projectCode);
		gt.putServiceTicket(st);
		
		TicketCache.putGrantingTicket(gt);
		TicketCache.putServiceTicket2GrantingTicket(st.getId(), gt.getId());
		
		if(service.contains("?"))
		{
			response.sendRedirect(service+"&ticket="+st.getId());
		}else
		{
			response.sendRedirect(service+"?ticket="+st.getId());
		}
	}
	
	
	/**
	 * 单点登录
	 * @param request
	 * @param response
	 * @param chain
	 * @throws IOException
	 * @throws ServletException
	 */
	public void signin(HttpServletRequest request, HttpServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		 String projectCode = request.getParameter("projectCode");
		 String service = request.getParameter("service");
		 String identity = request.getParameter("identity");
		 String password = request.getParameter("password");
		 
		 System.out.println("=============================signni param===============================");
		 System.out.println("projectCode="+projectCode);
		 System.out.println("service="+service);
		 System.out.println("identity="+identity);
		 System.out.println("password="+password);
		 
		 SSOIdentity ssoId = null;
		 //验证project不通过
		 String vali = validateProject(projectCode);
		 if(null!=vali)
		 {
			 ssoId = SSOIdentity.error(vali);
		 }else
		 {
			//用户验证
			UserAuthService userAuthentication = (UserAuthService)SpringBeanLoader.getBean("userAuthServiceImpl");
			ssoId = userAuthentication.verificationUser(identity, password);
		 }
		
		 //用户登录失败
		 if(ssoId.getType().equals(XJJConstants.MSG_TYPE_ERROR))
		 {
			 //如果是客户端的登录
			if(SSOUtils.isNotBlank(service))
			{
				String url = URLUtils.putParam2Url(service, SSO_SERVER_ERROR, ssoId.getMessage());
				url=URLUtils.putParam2Url(url, identity, identity);
				response.sendRedirect(url);
				return;
			}
			
			//服务器端的登录
			request.setAttribute("identity", identity);
			request.setAttribute("password", password);
			request.setAttribute(SSO_SERVER_ERROR,"usererror");
			request.getRequestDispatcher(SSO_URL_LOGIN).forward(request, response);
			return;
		 }
		 
		 //踢出其他地方已经登陆的本用户 
		 //ssoKickUser(request,response,ssoId.getUser());
		 
		 GrantingTicket gt = GrantingTicket.generateGrantingTicket(ssoId.getUser());
		 ServiceTicket st = GrantingTicket.generateServiceTicket(service);
		 st.setProjectCode(projectCode);
		 gt.putServiceTicket(st);
		 
		 TicketCache.putGrantingTicket(gt);
		 TicketCache.putServiceTicket2GrantingTicket(st.getId(), gt.getId());
		 
		 writeCookie(response,gt.getId());
		 
		 if(SSOUtils.isNotBlank(service))
		 {
			 response.sendRedirect(URLUtils.putParam2Url(service, "ticket", st.getId()));
		 }else
		 {
			 response.sendRedirect(request.getContextPath()+SSO_URL_INDEX+"?ticket="+st.getId());
		 }
		 return;
	}
	
	/**
	 * 单点退出
	 * @param request
	 * @param response
	 * @param chain
	 * @throws IOException
	 * @throws ServletException
	 */
	public void signout(HttpServletRequest request, HttpServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		String gtCookie = getSSOCookie(request, response);
		String service = request.getParameter("service");
		System.out.println("退出时得到的cookie值:"+gtCookie);
		if(SSOUtils.isNotBlank(gtCookie))
		{
			ssoLogout(request,response,gtCookie);
		}
		
		//如果有service 则跳转到service地址
		if(SSOUtils.isNotBlank(service))
		{
			sendRedirect(request,response,service,null);
			return;
		}
		
		String projectCode = request.getParameter("projectCode");
		//如果传来了projectCode ,则跳转到项目登录地址
		if(SSOUtils.isNotBlank(projectCode))
		{
			ProjectEntity p = ProjectCache.getByCode(projectCode);
			if(null != p)
			{
				sendRedirect(request, response, p.getLoginUrl(),null);
				return;
			}
		}
		sendRedirect(request,response,SSO_URL_LOGIN,null);
		return;
	}
	
	/**
	 * 验证ticket
	 * @param request
	 * @param response
	 * @param chain
	 * @throws IOException
	 * @throws ServletException
	 */
	public void validateTicket(HttpServletRequest request, HttpServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		String ticket =  request.getParameter("ticket");
		String service =  request.getParameter("service");
		
		String gTicket = TicketCache.getGTicket(ticket);
		GrantingTicket gt = TicketCache.getGrantingTicket(gTicket);
		
		System.out.println("===================sso validateTicket ticket ==="+ticket);
		System.out.println("===================sso validateTicket service ==="+service);
		System.out.println("===================sso validateTicket gTicket ==="+gTicket);
		System.out.println("===================sso validateTicket gt ==="+gt);
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		response.setHeader("Content-type", "text/html;charset=UTF-8"); 
		
		if(null == gTicket || null == gt)
		{
			response.getOutputStream().print("");
			return;
		}
		
		ServiceTicket st = gt.getServiceTicket(ticket, service);
		if(null != st)
		{
			System.out.println("===================sso validateTicket st ==="+st.toString());
			//使ticket失效
			TicketCache.expiredServiceTicket(st.getId());
			
			User user = gt.getUser();
			String json = JsonUtil.toJSONString(user);
			response.getOutputStream().write(json.getBytes("UTF-8"));
			System.out.println("===================sso validateTicket json ==="+json);
			return;
		}else
		{
			response.getOutputStream().print("");
		}
	}
}